home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SNNSV32.ZIP / SNNSv3.2 / kernel / sources / cc_rcc_topo.c < prev    next >
C/C++ Source or Header  |  1994-04-25  |  15KB  |  489 lines

  1. /*****************************************************************************
  2.   FILE           : cc_rcc_topo.c
  3.   SHORTNAME      : 
  4.   SNNS VERSION   : 3.2
  5.  
  6.   PURPOSE        : Functions of CC and RCC for topological check.
  7.   NOTES          :
  8.  
  9.   AUTHOR         : Michael Schmalzl
  10.   DATE           : 5.2.93
  11.  
  12.   CHANGED BY     : Michael Schmalzl
  13.   IDENTIFICATION : @(#)cc_rcc_topo.c    1.8 3/15/94
  14.   SCCS VERSION   : 1.8
  15.   LAST CHANGE    : 3/15/94
  16.  
  17.              Copyright (c) 1990-1994  SNNS Group, IPVR, Univ. Stuttgart, FRG
  18.  
  19. ******************************************************************************/
  20.  
  21. #include <stdio.h>
  22. #include <math.h>
  23. #include <time.h>  
  24. #include <memory.h>
  25. #include <malloc.h>
  26. #include <values.h>
  27.  
  28. #include "kr_typ.h"    
  29. #include "kr_const.h"     
  30. #include "kr_def.h"     
  31. #include "kr_mac.h"
  32. #include "kernel.h"
  33. #include "cc_mac.h"    
  34. #include "cc_rcc.h" 
  35. #include "cc_rcc_topo.ph"
  36.  
  37.  
  38. /*****************************************************************************
  39.   FUNCTION : cc_clearFlags
  40.  
  41.   PURPOSE  : Clears all CC flags.
  42.   NOTES    :
  43.  
  44.   UPDATE   : 5.2.93
  45. ******************************************************************************/
  46.  
  47. static void cc_clearFlags(void)
  48. {
  49.  struct Unit *unitPtr;
  50.  
  51.  FOR_ALL_UNITS(unitPtr){
  52.    if(UNIT_IN_USE(unitPtr)){
  53.      unitPtr->flags &= ~UFLAG_REFRESH;
  54.      unitPtr->lln = 0;
  55.      LINKS_LEAVING(unitPtr) = 0;
  56.      LINKS_ARRIVEING(unitPtr) = 0;
  57.      INPUT_LINKS(unitPtr) = 0;
  58.    }
  59.  }
  60.  
  61. /*****************************************************************************
  62.   FUNCTION : rcc_clearFlags
  63.  
  64.   PURPOSE  : Clears all RCC flags.
  65.   NOTES    :
  66.  
  67.   UPDATE   : 5.2.93
  68. ******************************************************************************/
  69.  
  70. static void rcc_clearFlags(void)
  71. {
  72.  struct Unit *unitPtr;
  73.  int flagMask;
  74.  
  75.  flagMask = RCC_FLAG | UFLAG_REFRESH;
  76.  FOR_ALL_UNITS(unitPtr){
  77.    if(UNIT_IN_USE(unitPtr)){
  78.      unitPtr->flags &= ~flagMask;
  79.      unitPtr->lln = 0;
  80.      LINKS_LEAVING(unitPtr) = 0;
  81.      LINKS_ARRIVEING(unitPtr) = 0;
  82.      INPUT_LINKS(unitPtr) = 0;
  83.    }
  84.  }
  85.  
  86. /*****************************************************************************
  87.   FUNCTION : cc_quicksort
  88.  
  89.   PURPOSE  : Sorts  the units of the hidden layer by  the number of incomming
  90.              links.
  91.   NOTES    :
  92.  
  93.   UPDATE   : 5.2.93
  94. ******************************************************************************/
  95.  
  96. static void cc_quicksort(int left, int right)
  97. {
  98.  int i,last;
  99.  struct Unit *temp;
  100.  
  101.  if(left >= right ){
  102.    return;
  103.  }
  104.  temp = FirstHiddenUnitPtr[left]; 
  105.  FirstHiddenUnitPtr[left] = FirstHiddenUnitPtr[(left+right)/2]; 
  106.  FirstHiddenUnitPtr[(left+right)/2] = temp;  
  107.  last = left; 
  108.  for(i=left+1;i<=right;i++){
  109.    if(LINKS_LEAVING(FirstHiddenUnitPtr[i]) < LINKS_LEAVING(FirstHiddenUnitPtr[left])) {
  110.      temp = FirstHiddenUnitPtr[++last]; 
  111.      FirstHiddenUnitPtr[last]=FirstHiddenUnitPtr[i]; 
  112.      FirstHiddenUnitPtr[i]=temp;
  113.    }
  114.  }
  115.  temp = FirstHiddenUnitPtr[left]; 
  116.  FirstHiddenUnitPtr[left]=FirstHiddenUnitPtr[last]; 
  117.  FirstHiddenUnitPtr[last] = temp;
  118.  cc_quicksort(left,last);
  119.  cc_quicksort(last+1,right);
  120. }
  121.  
  122.  
  123. /*****************************************************************************
  124.   FUNCTION : DepthFirst4
  125.  
  126.   PURPOSE  : Depth search routine for topological sorting.
  127.   NOTES    :
  128.  
  129.   UPDATE   : 5.2.93
  130. ******************************************************************************/
  131.  
  132. static void  DepthFirst4(struct Unit *unit_ptr, int depth )
  133. {
  134.   struct Site   *site_ptr;
  135.   struct Link   *link_ptr;
  136.  
  137.  
  138.   if (unit_ptr->flags & UFLAG_REFRESH)
  139.     {  /*  the 'touch' flag is set: don't continue search  */
  140.     topo_msg.src_error_unit = unit_ptr - unit_array; /*  store unit number  */
  141.  
  142.     if IS_OUTPUT_UNIT( unit_ptr )
  143.       {  /*  this output unit has a output connection to another unit  */
  144.       if (topo_msg.error_code == KRERR_NO_ERROR)
  145.         topo_msg.error_code = KRERR_O_UNITS_CONNECT;
  146.     }
  147.     else
  148.       if (unit_ptr->lln == 0)
  149.         {  /*  logical layer no. isn't set => Cycle found  */
  150.         topo_msg.no_of_cycles++;
  151.         if (topo_msg.error_code == KRERR_NO_ERROR)
  152.           topo_msg.error_code = KRERR_CYCLES;
  153.       }
  154.  
  155.     return;
  156.   }
  157.   else
  158.     /*  set the 'touch' flag  */
  159.     unit_ptr->flags |= UFLAG_REFRESH;
  160.  
  161.   switch (unit_ptr->flags & UFLAG_INPUT_PAT)
  162.     {
  163.     case  UFLAG_DLINKS:   /*  unit has direct links  */
  164.       FOR_ALL_LINKS(unit_ptr,link_ptr){
  165.         DepthFirst4( link_ptr->to, depth + 1 );  /*  increase depth  */
  166.         if(IS_INPUT_UNIT(link_ptr->to)){
  167.           INPUT_LINKS(unit_ptr)++;
  168.         }
  169.         if((IS_HIDDEN_UNIT(link_ptr->to)) && (IS_HIDDEN_UNIT(unit_ptr))){
  170.           LINKS_LEAVING(link_ptr->to)++;
  171.           LINKS_ARRIVEING(unit_ptr)++;
  172.         }
  173.       }
  174.       break;
  175.     case  UFLAG_SITES:  /*  unit has sites  */
  176.       FOR_ALL_SITES_AND_LINKS(unit_ptr,site_ptr, link_ptr) {
  177.         DepthFirst4( link_ptr->to, depth + 1 );  /*  increase depth  */
  178.         if(IS_INPUT_UNIT(link_ptr->to)){
  179.           INPUT_LINKS(unit_ptr)++;
  180.         }
  181.         if((IS_HIDDEN_UNIT(link_ptr->to)) && (IS_HIDDEN_UNIT(unit_ptr))){
  182.           LINKS_LEAVING(link_ptr->to)++;
  183.           LINKS_ARRIVEING(unit_ptr)++;
  184.         }
  185.       }
  186.       break;
  187.   }
  188.  
  189.   /*  remember the depth (for cycle detection and statistics)  */
  190.   unit_ptr->lln = depth;
  191.  
  192.   /*  store only hidden units  */
  193.   if IS_HIDDEN_UNIT( unit_ptr )
  194.     *global_topo_ptr++ = unit_ptr;  /*  store sorted unit pointer  */
  195. }
  196.  
  197. /*****************************************************************************
  198.   FUNCTION : DepthFirst5
  199.  
  200.   PURPOSE  : Depth search routine for topological sorting.
  201.   NOTES    :
  202.  
  203.   UPDATE   : 5.2.93
  204. ******************************************************************************/
  205.  
  206. static void  DepthFirst5( unit_ptr, depth )
  207. struct Unit   *unit_ptr;
  208. int     depth;
  209. {
  210.   struct Site   *site_ptr;
  211.   struct Link   *link_ptr;
  212.  
  213.  
  214.   if (unit_ptr->flags & UFLAG_REFRESH)
  215.     {  /*  the 'touch' flag is set: don't continue search  */
  216.     topo_msg.src_error_unit = unit_ptr - unit_array; /*  store unit number  */
  217.  
  218.     if IS_OUTPUT_UNIT( unit_ptr )
  219.       {  /*  this output unit has a output connection to another unit  */
  220.       if (topo_msg.error_code == KRERR_NO_ERROR)
  221.         topo_msg.error_code = KRERR_O_UNITS_CONNECT;
  222.     }
  223.     else
  224.       if (unit_ptr->lln == 0)
  225.         {  /*  logical layer no. isn't set => Cycle found  */
  226.         topo_msg.no_of_cycles++;
  227.         if (topo_msg.error_code == KRERR_NO_ERROR)
  228.           topo_msg.error_code = KRERR_CYCLES;
  229.       }
  230.  
  231.     return;
  232.   }
  233.   else
  234.     /*  set the 'touch' flag  */
  235.     unit_ptr->flags |= UFLAG_REFRESH;
  236.  
  237.   switch (unit_ptr->flags & UFLAG_INPUT_PAT)
  238.     {
  239.     case  UFLAG_DLINKS:   /*  unit has direct links  */
  240.       FOR_ALL_LINKS(unit_ptr,link_ptr) {
  241.         if((IS_HIDDEN_UNIT(unit_ptr)) && (link_ptr->to == unit_ptr)) {
  242.           if(unit_ptr->flags & RCC_FLAG) {
  243.             topo_msg.error_code = KRERR_CC_ERROR4; /* too manny recurent links */
  244.           }
  245.           else { 
  246.             unit_ptr->flags |= RCC_FLAG;
  247.           }
  248.         }
  249.         else { 
  250.           DepthFirst5( link_ptr->to, depth + 1 );  /*  increase depth  */
  251.           if(IS_INPUT_UNIT(link_ptr->to)){
  252.             INPUT_LINKS(unit_ptr)++;
  253.           }
  254.           if((IS_HIDDEN_UNIT(link_ptr->to)) && (IS_HIDDEN_UNIT(unit_ptr))){
  255.             LINKS_LEAVING(link_ptr->to)++;
  256.             LINKS_ARRIVEING(unit_ptr)++;
  257.           }
  258.         }
  259.       }
  260.       break;
  261.     case  UFLAG_SITES:  /*  unit has sites  */
  262.       FOR_ALL_SITES_AND_LINKS(unit_ptr,site_ptr, link_ptr) {
  263.         if((IS_HIDDEN_UNIT(unit_ptr)) && (link_ptr->to == unit_ptr)) {
  264.           if(unit_ptr->flags & RCC_FLAG) {
  265.             topo_msg.error_code = KRERR_CC_ERROR4; /* too many recurent links */
  266.           }
  267.           else { 
  268.             unit_ptr->flags |= RCC_FLAG;
  269.           }
  270.         }
  271.         else { 
  272.           DepthFirst5( link_ptr->to, depth + 1 );  /*  increase depth  */
  273.           if(IS_INPUT_UNIT(link_ptr->to)){
  274.             INPUT_LINKS(unit_ptr)++;
  275.           }
  276.           if((IS_HIDDEN_UNIT(link_ptr->to)) && (IS_HIDDEN_UNIT(unit_ptr))){
  277.             LINKS_LEAVING(link_ptr->to)++;
  278.             LINKS_ARRIVEING(unit_ptr)++;
  279.           }
  280.         }
  281.       }
  282.       break;
  283.     }
  284.  
  285.   /*  remember the depth (for cycle detection and statistics)  */
  286.   unit_ptr->lln = depth;
  287.  
  288.   /*  store only hidden units  */
  289.   if IS_HIDDEN_UNIT( unit_ptr )
  290.     *global_topo_ptr++ = unit_ptr;  /*  store sorted unit pointer  */
  291. }
  292.  
  293. /*****************************************************************************
  294.   FUNCTION : cc_topoSort
  295.  
  296.   PURPOSE  : Main routine for topological sorting for CC and RCC.
  297.   NOTES    :
  298.  
  299.   UPDATE   : 5.2.93
  300. ******************************************************************************/
  301.  
  302. krui_err cc_topoSort(int topoSortId)
  303. {
  304.   register struct Unit   *unit_ptr;
  305.   int   io_units,h,counter=0,recurentLinkDetected;
  306.   struct Link *link_ptr;
  307.   
  308.   KernelErrorCode = KRERR_NO_ERROR;  /*  reset return code  */
  309.   if(topoSortId == TOPOLOGICAL_CC) {
  310.     cc_clearFlags();    /*  reset units 'touch' flags  */
  311.   }
  312.   else {
  313.     rcc_clearFlags();
  314.   }
  315.   global_topo_ptr = topo_ptr_array;  /*  initialize global pointer */
  316.  
  317.   /*  limit left side of the topological array with NULL pointer  */
  318.   *global_topo_ptr++ = NULL;
  319.  
  320.   /*  put all input units in the topologic array  */
  321.   io_units = 0;
  322.   FOR_ALL_UNITS( unit_ptr ) 
  323.     if (IS_INPUT_UNIT( unit_ptr ) && UNIT_IN_USE( unit_ptr ))
  324.       {
  325.       if UNIT_HAS_INPUTS( unit_ptr )
  326.         {  /*  this input unit has a connection to another unit  */
  327.         topo_msg.dest_error_unit = unit_ptr - unit_array;  /*  store the unit no.  */
  328.  
  329.         KernelErrorCode = KRERR_I_UNITS_CONNECT;  /*  input unit has input  */
  330.         return( KernelErrorCode );
  331.       }
  332.  
  333.       io_units++;       /*  there is a input unit  */
  334.       *global_topo_ptr++ = unit_ptr;  /*  save input unit  */
  335.     }
  336.   
  337.   if ((NoOfInputUnits = io_units) == 0)
  338.     {  /*  no input units */
  339.     KernelErrorCode = KRERR_NO_INPUT_UNITS;
  340.     return( KernelErrorCode );
  341.   }
  342.  
  343.   /*  limit input units in the topological array with NULL pointer  */
  344.   *global_topo_ptr++ = NULL;
  345.  
  346.   /*  begin depth search at the first output unit  */
  347.   io_units = 0;
  348.   FOR_ALL_UNITS( unit_ptr )
  349.     if (IS_OUTPUT_UNIT( unit_ptr ) && UNIT_IN_USE( unit_ptr ))
  350.       {
  351.       io_units++;       /*  there is a output unit  */
  352.       if(topoSortId == TOPOLOGICAL_CC){
  353.         DepthFirst4( unit_ptr, 1 );
  354.       }
  355.       else if (topoSortId == TOPOLOGICAL_RCC){
  356.         DepthFirst5(unit_ptr,1);
  357.       }
  358.       else { /* topoSortId == TOPOLOGICAL_BCC */ 
  359.         DepthFirst4(unit_ptr,1);
  360.       }      
  361.       if (topo_msg.error_code != KRERR_NO_ERROR)
  362.         {  /*  stop if an error occured  */
  363.         KernelErrorCode = topo_msg.error_code;
  364.         return( KernelErrorCode );
  365.       }
  366.     }
  367.  
  368.  
  369.   if ((NoOfOutputUnits = io_units) == 0)
  370.     {  /*  no output units */
  371.     KernelErrorCode = KRERR_NO_OUTPUT_UNITS;
  372.     return( KernelErrorCode );
  373.   }
  374.  
  375.   /*  limit hidden units in the topological array with NULL pointer  */
  376.   *global_topo_ptr++ = NULL;
  377.  
  378.   /*  put all output units in the topological array  */
  379.   FOR_ALL_UNITS( unit_ptr ) 
  380.     if (IS_OUTPUT_UNIT(unit_ptr ) && UNIT_IN_USE( unit_ptr ))
  381.       *global_topo_ptr++ = unit_ptr;  /*  save output unit  */
  382.  
  383.   /*  limit right side of the topologic array with NULL pointer  */
  384.   *global_topo_ptr++ = NULL;
  385.   
  386.   FOR_ALL_UNITS( unit_ptr ) {
  387.     if (IS_SPECIAL_UNIT(unit_ptr) && UNIT_IN_USE( unit_ptr )) {
  388.       if(topoSortId == TOPOLOGICAL_RCC){
  389.         link_ptr = (struct Link *) unit_ptr->sites;
  390.         if(unit_ptr != link_ptr->to) {
  391.           KernelErrorCode = KRERR_CC_ERROR9; /* the first link is not a recurent link */
  392.           return(KernelErrorCode);
  393.         }
  394.         recurentLinkDetected = 0;
  395.         if(topoSortId == TOPOLOGICAL_RCC) {   
  396.           FOR_ALL_LINKS(unit_ptr,link_ptr){
  397.             if(unit_ptr == link_ptr->to) {
  398.               recurentLinkDetected++;
  399.             }
  400.           }
  401.           if(recurentLinkDetected != 1) {   
  402.             KernelErrorCode = KRERR_CC_ERROR8; /* the special unit has too many links */
  403.             return( KernelErrorCode ); 
  404.       }
  405.     }
  406.       }
  407.       *global_topo_ptr++ = unit_ptr;  /*  save output unit  */
  408.       unit_ptr->flags |= UFLAG_REFRESH;
  409.     }
  410.   }
  411.   /*  limit right side of the topologic array with NULL pointer  */
  412.   *global_topo_ptr++ = NULL;
  413.  
  414.   /*  calc. no. of sorted units  */
  415.   no_of_topo_units = (global_topo_ptr - topo_ptr_array) - 5;
  416.  
  417.   /*  search for dead units i.e. units without inputs  */
  418.   FOR_ALL_UNITS( unit_ptr )
  419.     if (!(unit_ptr->flags & UFLAG_REFRESH) && UNIT_IN_USE( unit_ptr ))
  420.       {
  421.       topo_msg.no_of_dead_units++;
  422.       if (topo_msg.src_error_unit == 0)
  423.         topo_msg.src_error_unit = unit_ptr - unit_array;  /*  store the unit no.  */
  424.     }
  425.  
  426.   if (topo_msg.no_of_dead_units != 0)
  427.     KernelErrorCode = KRERR_DEAD_UNITS;
  428.  
  429.   if(KernelErrorCode == KRERR_NO_ERROR){
  430.     FirstHiddenUnitPtr = (struct Unit **)(&topo_ptr_array[1]) + NoOfInputUnits + 1;
  431.     FOR_ALL_HIDDEN_UNITS(unit_ptr,h){
  432.        switch(topoSortId){
  433.          case TOPOLOGICAL_RCC : 
  434.            if(!(unit_ptr->flags & RCC_FLAG)) {
  435.              KernelErrorCode = KRERR_CC_ERROR5;
  436.            }
  437.            if((LINKS_LEAVING(unit_ptr)+LINKS_ARRIVEING(unit_ptr)+1)!=NoOfHiddenUnits) {
  438.              KernelErrorCode = KRERR_CC_ERROR6;
  439.              return(KernelErrorCode);
  440.            }
  441.            if(LINKS_ARRIVEING(unit_ptr) != counter++) {
  442.              KernelErrorCode = KRERR_CC_ERROR6;
  443.              return(KernelErrorCode);
  444.            }
  445.            link_ptr = (struct Link *) unit_ptr->sites;
  446.            if(unit_ptr != link_ptr->to) {
  447.              KernelErrorCode = KRERR_CC_ERROR7; /* the first link is not the recurent link */
  448.              return(KernelErrorCode);
  449.            }
  450.          break;
  451.          case TOPOLOGICAL_CC : 
  452.            if((LINKS_LEAVING(unit_ptr)+LINKS_ARRIVEING(unit_ptr)+1)!=NoOfHiddenUnits) {
  453.              fprintf(stderr,"111111 %d \n",NoOfHiddenUnits);
  454.              KernelErrorCode = KRERR_CC_ERROR6;
  455.              return(KernelErrorCode);
  456.            }
  457.            if(LINKS_ARRIVEING(unit_ptr) != counter++) {
  458.              fprintf(stderr,"22222 %d \n",counter);
  459.              KernelErrorCode = KRERR_CC_ERROR6;
  460.              return(KernelErrorCode);
  461.            }
  462.          break;
  463.          case TOPOLOGICAL_BCC : 
  464.            if((LINKS_LEAVING(unit_ptr)+LINKS_ARRIVEING(unit_ptr)+1)!=NoOfHiddenUnits) {
  465.              KernelErrorCode = KRERR_CC_ERROR6;
  466.              return(KernelErrorCode);
  467.            }
  468.            if(LINKS_ARRIVEING(unit_ptr) != counter++) {
  469.              KernelErrorCode = KRERR_CC_ERROR6;
  470.              return(KernelErrorCode);
  471.            }
  472.            if(counter == NoOfHiddenUnits) {
  473.              counter = 0;
  474.            }
  475.          break;
  476.        }  
  477.     }
  478.   }
  479.   return( KernelErrorCode );
  480. }
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.